<?php
/**
 * [LupMisNotAllowedSync]
 * 本代码为系统自动生成代码，请根据自己业务进行修改;
 * 生成时间 2022-02-01 22:12:12;
 * 版权所有 2020-2022 lizhongwen，并保留所有权利;
 * 说明: 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；不允许对程序代码以任何形式任何目的的再发布;
 * 作者: 中文Lee;
 * 作者主页: http://www.lizhongwen.com;
 * 邮箱: 360811363@qq.com;
 * QQ: 360811363;
 */

namespace application\core;

use Exception;

class Core
{

    /**
     * 运行程序
     */
    public function run()
    {
        date_default_timezone_set('PRC');
        header("Server:chunked");
        header("X-Powered-By:LUP");
        include APP_PATH . 'application/config/config.php';
        include APP_PATH . 'application/config/config-common.php';
        $configFile = sprintf("%s" . "application/config/config-%s.php", APP_PATH, PROFILES);
        $config = include "$configFile";
        set_time_limit(SET_TIME_LIMIT);
        ini_set("memory_limit", SET_MEMORY_LIMIT);
        if (CROSS_ENABLE) {
            header("Access-Control-Allow-Origin: *");
        }
        define('DB_CONFIG', json_encode($config['db']));
        define('REDIS', json_encode($config['redis']));
        unset($config['db']);
        unset($config['redis']);
        // 开发环境处理异常
        if (APP_DEBUG) {
            set_exception_handler(function ($e) {
                echo $e;
            });
            error_reporting(E_ALL & ~E_NOTICE);
            ini_set('display_errors', 'On');
        } else {
            error_reporting(0);
        }
        spl_autoload_register([
            $this,
            'loadClass'
        ]);
        // 加载路由
        try {
            $this->route();
        } catch (Exception $e) {
            if (APP_DEBUG) {
                echo "<pre>";
                print_r($e);
            } else {
                http_response_code(500);
                Lib::outputJson(Result::fail(true, $e->getMessage(), '服务器内部错误', 500));
            }
        }
    }

    /**
     * 路由处理
     *
     * @throws Exception
     */
    private function route()
    {
        $controllerName = 'index';
        $actionName = 'index';
        $param = [];
        $url = $_SERVER['REQUEST_URI'];
        // 清除?之后的内容
        $position = strpos($url, '?');
        $url = ($position === false) ? $url : substr($url, 0, $position);
        // 删除前后的/
        $url = substr($url, 1);
        $url = preg_replace('/([^:])([\/\\\\]+([.][\/\\\\]+)+|[\/\\\\]{2,})/', '$1/', $url);
        $url = preg_replace('#/$#', '', $url);
        if (strtolower($url) == 'index.php')
            $url = '';
        if (!empty($url)) {
            $url = ltrim($url, '/');
            $urlArray = explode('/', $url);
            $urlArray = array_filter($urlArray);
            if ('web' == $urlArray[0]) {
                define('RUN_PATH', strtolower('web'));
            } else {
                $modulesName = MODULES_NAME;
                if (!$modulesName[$urlArray[0]]) {
                    define('RUN_PATH', strtolower('web'));
                } else {
                    define('RUN_PATH', strtolower($urlArray[0]));
                }
            }
        } else {
            define('RUN_PATH', strtolower('web'));
        }
        if ($url) {
            // 使用/分割字符串，并保存在数组中
            $url = ltrim($url, '/');
            $urlArray = explode('/', $url);
            foreach ($urlArray as $k => $v) {
                if (!isset($v)) {
                    unset($urlArray[$k]);
                }
            }
            if ('web' != RUN_PATH) {
                // 获取控制器名
                $controllerName = isset($urlArray[1]) ? ucfirst($urlArray[1]) : $controllerName;
                unset($urlArray[0]);
                // 获取动作名
                // 获取URL参数
            } else {
                // 获取控制器名
                $controllerName = isset($urlArray[0]) ? ucfirst($urlArray[0]) : $controllerName;
                // 获取动作名
                // 获取URL参数
            }
            array_shift($urlArray);
            $actionName = !empty($urlArray[0]) ? $urlArray[0] : $actionName;
            array_shift($urlArray);
            $param = $urlArray ?: [];
        }
        // 加载过滤器
        $filter = new Filter();
        $filter->run($controllerName, $actionName, $param);
        // 判断控制器和操作是否存在
        $controllerPath = Filter::$controllerPath;
        if (!class_exists($controllerPath)) {
//            header("HTTP/1.1 404 Not Found");
//            header("Status: 404 Not Found");
            http_response_code(404);
            header("Content-Type:application/json; charset=utf-8");
            //重定义404
            $arr = ['code' => 404, 'msg' => 'controller资源不存在'];
            echo json_encode($arr, JSON_UNESCAPED_UNICODE);
            //throw new Exception($controllerName . 'Controller控制器不存在');
            return;
        }

        if (!method_exists($controllerPath, $actionName)) {
            http_response_code(404);
//            header("HTTP/1.1 404 Not Found");
//            header("Status: 404 Not Found");
            header("Content-Type:application/json; charset=utf-8");
            $arr = ['code' => 404, 'msg' => 'function资源不存在'];
            echo json_encode($arr, JSON_UNESCAPED_UNICODE);
            //throw new Exception($actionName . '方法不存在');
            return;
        }
        $dispatch = new $controllerPath($controllerName, $actionName);
        // $dispatch保存控制器实例化后的对象，我们就可以调用它的方法，
        $result = call_user_func_array([
            $dispatch,
            $actionName
        ], $param);
        if (is_array($result)) {
            header("Content-Type:application/json; charset=utf-8");
            echo json_encode($result, JSON_UNESCAPED_UNICODE);
        } else {
            echo $result;
        }
    }

    /**
     * 自动加载类
     * @param $className
     */
    private function loadClass($className)
    {
        $classMap = $this->classMap();
        if (isset($classMap[$className])) {
            // 包含内核文件
            $file = $classMap[$className];
            include "$file";
        } elseif (strpos($className, '\\') !== false) {
            // 包含应用（modules目录）文件
            $file = sprintf("%s" . "%s.php", APP_PATH, str_replace('\\', '/', $className));
            if (file_exists($file)) {
                include "$file";
            }
        }
    }

    /**
     * 内核文件命名空间映射关系
     *
     * @return string[]
     */
    private function classMap(): array
    {
        return [
            'application\core\Filter' => APP_PATH . 'application/core/Filter.php',
            'application\core\Lib' => APP_PATH . 'application/core/Lib.php',
            'application\core\Request' => APP_PATH . 'application/core/Request.php',
            'application\core\Date' => APP_PATH . 'application/core/Date.php',
            'application\core\RedisUtil' => APP_PATH . 'application/core/RedisUtil.php',
            'application\core\Controller' => APP_PATH . 'application/core/Controller.php',
            'application\core\Mapper' => APP_PATH . 'application/core/Mapper.php',
            'application\core\db\Db' => APP_PATH . 'application/core/Db.php'
        ];
    }
}